<?php
/**
 * Created by PhpStorm.
 * User: peter
 * Date: 2018/9/10
 * Time: 上午11:52
 */

namespace app\activity\controller;


use app\model\MemberLoginToken;
use extend\Functions;
use extend\STATUS_CODE;
use Naixiaoxin\ThinkWechat\Facade;
use think\facade\Cache;
use think\Request;

class Sign extends Base
{
    /**
     * @purpose 注册
     * @param Request $request
     * @return array
     * @throws \think\exception\PDOException
     */
    public function register(Request $request)
    {
        $data = $request->post();

        if (!$data['nickname']) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '昵称不能为空'
            );
        }
        if (!$data['username']) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '用户名不能为空'
            );
        }
        if (!$data['mobile']) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '手机号码不能为空'
            );
        }
        if (!$data['code']) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '验证码不能为空'
            );
        }
        if (!$data['password']) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '密码不能为空'
            );
        }
        $data['username'] = strtolower(trim($data['username']));
        $data['password'] = strtolower(trim($data['password']));
        if (!preg_match('/^(?!\d+$)[\da-zA-Z]{6,}$/', $data['username'])) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '用户名格式错误，由6位以上，字母或数字组合'
            );
        }
        if (!preg_match('/^(?!\d+$)[\da-zA-Z]{6,}$/', $data['password'])) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '密码格式错误，由6位以上，字母或数字组合'
            );
        }
        if (!Functions::check_mobile($data['mobile'])) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '手机号码格式错误'
            );
        }
        if (\app\model\Member::M()->where('username', $data['username'])->count() > 0) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '用户名已存在'
            );
        }
        if (\app\model\Member::M()->where('mobile', $data['mobile'])->count() > 0) {
            return self::response(
                STATUS_CODE::PARAMETER_ERROR,
                '手机号码已存在'
            );
        }
        $selfCode = (string)Cache::store('redis')->get($data['mobile']);
        if (!$selfCode) {
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                '验证码已过期..!'
            );
        }
        if ($selfCode !== $data['code']) {
            return Functions::result(
                STATUS_CODE::PARAMETER_ERROR,
                '验证码错误...!'
            );
        }
        // 验证码验证成功清除验证码缓存
        Cache::store('redis')->rm($data['mobile']);
        // 组装用户数据
        $member_data             = Functions::password(strtolower(trim($data['password'])));
        $member_data['mobile']   = $data['mobile'];
        $member_data['nickname'] = $data['nickname'];
        $member_data['username'] = $data['username'];
        // 生产用户uuid
        $member_data['uuid'] = strtolower(Functions::getUUID());
        RE_UUID:
        $member_data['uuid'] = strtolower(Functions::getUUID());
        if (\app\model\Member::M()->where('uuid', $member_data['uuid'])->count(1) > 0) {
            goto RE_UUID;
        }
        $member_data['create_ip']       = $request->ip();
        $member_data['last_login_ip']   = $request->ip();
        $member_data['now_ip']          = $request->ip();
        $member_data['last_login_time'] = time();
        $member_data['now_time']        = time();
        $member = \app\model\Member::M();
        $login  = MemberLoginToken::M();
        $member->startTrans();
        $register_result = $member
            ->isUpdate(false)
            ->data($member_data)
            ->save();
        // 构建用户登录数据
        $login_data                          = [];
        $login_data['uid']                   = $member->uid;
        $login_data[self::$client_type . '_token'] = strtolower(Functions::getUUID());
        RE_LOGIN_TOKEN:
        $login_data[self::$client_type . '_token'] = strtolower(Functions::getUUID());
        if ($login->where(self::$client_type . '_token', $login_data[self::$client_type . '_token'])->count(1) > 0) {
            goto RE_LOGIN_TOKEN;
        }
        $login_result = $login
            ->isUpdate(false)
            ->data($login_data)
            ->save();
        if ($register_result && $login_result) {
            $member->commit();
            return self::response(
                STATUS_CODE::SUCCESS,
                [
                    'status' => STATUS_CODE::SUCCESS,
                    'token'  => $login_data[self::$client_type . '_token'],
                ]
            );
        }
        $member->rollback();
        return self::response(
            STATUS_CODE::SUCCESS,
            [
                'status' => STATUS_CODE::FAIL,
            ]
        );
    }

    /**
     * @purpose APP微信登录获取用户unionid(解决ios授权前端拿不到unionid问题)
     * @param Request $request
     * @return array
     * @throws \Exception
     */
    public function getUserInfoByAppWechatAuth(Request $request)
    {
        $openId      = $request->post('openid');
        $accessToken = $request->post('access_token');
        // 获取access_token
//        $url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='.config('app.open_wechat.appid').'&secret='.config('app.open_wechat.secret').'&code='.$code.'&grant_type=authorization_code';
//        $accessToken = Functions::getAccessToken();
//        $openId = $request->post('openid');
        $url    = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $accessToken . '&openid=' . $openId . '&lang=zh_CN';
        $result = \Requests::get($url);
        $result = json_decode($result->body, true);
        return Functions::result($result);
    }

    /**
     * @purpose 获取微信端当前访问用户的用户信息
     * @param Request $request
     * @return array
     */
    public function getNowWechatUserInfo(Request $request)
    {
        $code = $request->get('code');
        return \app\activity\logic\Sign::getNowWechatUserInfo($code);
    }

    /**
     * @purpose 找回密码
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function findPassword(Request $request): array
    {
        $mobile   = $request->post('mobile', '');
        $code     = $request->post('code', '');
        $password = $request->post('password', '');
        return \app\activity\logic\Sign::findPassword($mobile, $code, $password);
    }

    /**
     * @APP端微信直接注册
     * @param Request $request
     * @return array
     * @throws \think\exception\PDOException
     */
    public function registerForNative(Request $request): array
    {
        $data = $request->post();
        return \app\activity\logic\Sign::registerForNative($data);
    }

    /**
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function registerByMobileForNative(Request $request): array
    {
        $data = $request->post();
        return \app\activity\logic\Sign::registerByMobileForNative($data);
    }

    /**
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function registerByUsernameForNative(Request $request): array
    {
        $data = $request->post();
        return \app\activity\logic\Sign::registerByUsernameForNative($data);
    }

    /**
     * @purpose 检测APP端微信unionid是否已经注册，如果已经注册则直接返回token
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function checkUnionIdForNative(Request $request): array
    {
        $unionid = $request->post('unionid', '');
        return \app\activity\logic\Sign::checkUnionIdForNative($unionid);
    }

    /**
     * @purpose 通过用户名密码绑定
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function registerByMobile(Request $request)
    {
        $bind_key = $request->post('bind_key', '');
        $mobile   = $request->post('mobile', '');
        $code     = $request->post('code', '');
        return \app\activity\logic\Sign::registerByMobile($mobile, $code, $bind_key);
    }

    /**
     * @purpose 通过用户名密码绑定
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function registerByUsername(Request $request)
    {
        $bind_key = $request->post('bind_key', '');
        $username = $request->post('username', '');
        $password = $request->post('password', '');
        return \app\activity\logic\Sign::registerByUsername($username, $password, $bind_key);
    }

    /**
     * @purpose 通过授权缓存的用户信息key注册
     * @param Request $request
     * @return array
     * @throws \think\exception\PDOException
     */
    public function registerByKey(Request $request)
    {
        $bind_key = $request->post('bind_key', '');
        return \app\activity\logic\Sign::registerByKey($bind_key);
    }

    /**
     * @purpose 用户名密码登录
     * @param Request $request
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function signInByPassword(Request $request)
    {
        $username = $request->post('username', '');
        $password = $request->post('password', '');
        return \app\activity\logic\Sign::signInByPassword($username, $password, self::$client_type);
    }

    /**
     * @purpose 获取公众号appid,给前端公众号授权使用
     * @return array
     */
    public function officialAccountAppId()
    {
        return Functions::result(
            STATUS_CODE::SUCCESS,
            [
                'appid' => config('wechat.official_account.default.app_id'),
            ]
        );
    }

    /**
     * @purpose 获取jssdk 签名
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    public function jsSdk(Request $request)
    {
        $url = $request->get('url', config('client_domain'));
        $app = Facade::officialAccount();
        $api = ['onMenuShareTimeline',
                'onMenuShareAppMessage',
                'onMenuShareQQ',
                'onMenuShareWeibo',
                'onMenuShareQZone',
                'startRecord',
                'stopRecord',
                'onVoiceRecordEnd',
                'playVoice',
                'pauseVoice',
                'stopVoice',
                'onVoicePlayEnd',
                'uploadVoice',
                'downloadVoice',
                'chooseImage',
                'previewImage',
                'uploadImage',
                'downloadImage',
                'translateVoice',
                'getNetworkType',
                'openLocation',
                'getLocation',
                'hideOptionMenu',
                'showOptionMenu',
                'hideMenuItems',
                'showMenuItems',
                'hideAllNonBaseMenuItem',
                'showAllNonBaseMenuItem',
                'closeWindow',
                'scanQRCode',
                'chooseWXPay',
                'openProductSpecificView',
                'addCard',
                'chooseCard',
                'openCard'];
        $app->jssdk->setUrl($url);
        $sign = $app->jssdk->buildConfig($api, false, false, false);
        return Functions::result(
            STATUS_CODE::SUCCESS,
            $sign
        );
    }

    /**
     * @purpose 用户登录、注册、更换token
     * @param Request $request
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\HttpException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function token(Request $request)
    {
        $token = $request->get('token', '');
        $code  = $request->get('code', '');
        return \app\activity\logic\Sign::token($code, $token, self::$client_type);
    }
}